import { FileUtils } from '~/core/extensions';
import { adapter } from '~/adapter/Adapter';
import { DefaultLinterOptions, LinterOptions } from './Options';
import { QVoGEngine } from '~/core/engine';
import { Queryable } from '~/core/dsl';
import { DslRules, NativeRules } from '~/rule';
import { Configuration } from '~/core/Configuration';
import { ArkTsSpecification } from '~/language';

const logger = Configuration.getLogger('linter');

export async function run(cwd?: string): Promise<void> {
    if (cwd) {
        // switch to the specified directory
        process.chdir(cwd);
    }
    logger.info(`Running QVoG Linter in ${process.cwd()}`);

    const options = loadOptions(`qvog.config.json`);
    parseOptions(options);

    // prepare engine
    const engine = new QVoGEngine(options.engine);

    // prepare rules
    const queries: Queryable[] = [];
    for (const rule of NativeRules) {
        if (rule[2] === 'on') {
            queries.push(rule[1]);
        }
    }

    for (const dsl of DslRules) {
        if (dsl[1] === 'on') {
            queries.push(adapter.loadDslRule(dsl[0]));
        }
    }

    // run!
    await engine.submitAsync(queries);
}

function loadOptions(file: string): LinterOptions {
    if (FileUtils.exists(file)) {
        return JSON.parse(FileUtils.readTextFile(file));
    } else {
        logger.warn(`File ${file} not found. Using default options.`);
        return DefaultLinterOptions;
    }
}

function parseOptions(options: LinterOptions): void {
    switch (options.language || 'arkts') {
        case 'arkts':
            Configuration.setSpecification(ArkTsSpecification);
            break;
        default:
            throw new Error(`Unsupported language: ${options.language}`);
    }
}
